package abacab.ref;

import abacab.ActorSystemImpl;
import abacab.actor.ActorDef;
import abacab.exec.MessageExecutor;
import abacab.message.Envelope;
import abacab.router.Router;
import abacab.router.RouterHandler;

import com.typesafe.config.ConfigException;

/**
 * An {@link ActorRef} referencing only one actor
 * 
 * @param <M>
 *          the type of messages handled by the actor(s)
 */
public class LocalActorRef<M> extends AbstractActorRef<M> {
	/** The executor */
	private final MessageExecutor	executor;

	/** The router */
	private final Router<M>				router;

	/**
	 * Create an instance
	 * 
	 * @param reference
	 *          the reference's name
	 * @param system
	 *          the actor system it belongs to
	 * @param definition
	 *          the actor's definition
	 * @throws ConfigException
	 *           if the configuration is invalid
	 */
	public LocalActorRef(String reference, ActorSystemImpl system, ActorDef<M> definition) throws ConfigException {
		super(reference, system);
		this.executor = system.getMessageExecutorFactory().getMessageExecutor(system, definition);
		this.router = RouterHandler.buildRouter(this, definition);
	}

	@Override
	public <N> void send(M message, ActorRef<N> sender) {
		this.router.send(this.executor, new Envelope<M>(sender, message));
	}
}